import { CanActivate, Injectable, ExecutionContext } from "@nestjs/common";
import { Request } from "express";

import { ENUM_ERROR, ENUM_USER, RestDto } from "qqlx-core";
import { toString } from "qqlx-cdk";

import { UserRpc } from "../rpc/app.stream-user";

@Injectable()
export class UserSuperGuard implements CanActivate {
  constructor(
    //
    private readonly UserRpc: UserRpc,
  ) {}

  async canActivate(context: ExecutionContext) {
    const _req: Request = context.switchToHttp().getRequest();
    const SessionId = toString(_req.cookies?.["SessionId"] || _req.header("SessionId"));
    const [{ uuid32, type }, super_user] = await Promise.all([this.UserRpc.getUserInfoBySessionId({ SessionId }), this.UserRpc.getFirstUser()]);

    const isAccountOK = super_user.uuid32 === uuid32;
    if (!isAccountOK) throw { code: ENUM_ERROR.ACCOUNT_TYPE_UNKNOW };

    _req.body.dto = { ..._req.body.dto, visitorId: uuid32, visitorType: type } as RestDto;
    return true;
  }
}

@Injectable()
export class UserPrimaryGuard implements CanActivate {
  constructor(
    private readonly UserRpc: UserRpc,
    //
  ) {}

  async canActivate(context: ExecutionContext) {
    const _req: Request = context.switchToHttp().getRequest();
    const SessionId = toString(_req.cookies?.["SessionId"] || _req.header("SessionId"));

    const { uuid32, type } = await this.UserRpc.getUserInfoBySessionId({ SessionId });
    const isAccountOK = type === ENUM_USER.PRIMARY;
    if (!isAccountOK) throw { code: ENUM_ERROR.DROIT_BELOW };

    _req.body.dto = { ..._req.body.dto, visitorId: uuid32, visitorType: type } as RestDto;
    return true;
  }
}

@Injectable()
export class UserDeriveGuard implements CanActivate {
  constructor(
    private readonly UserRpc: UserRpc,
    //
  ) {}

  async canActivate(context: ExecutionContext) {
    const _req: Request = context.switchToHttp().getRequest();
    const SessionId = toString(_req.cookies?.["SessionId"] || _req.header("SessionId"));

    const { uuid32, type } = await this.UserRpc.getUserInfoBySessionId({ SessionId });
    const isAccountOK = [ENUM_USER.PRIMARY, ENUM_USER.DERIVED].includes(type);
    if (!isAccountOK) throw { code: ENUM_ERROR.ACCOUNT_TYPE_UNKNOW };

    _req.body.dto = { ..._req.body.dto, visitorId: uuid32, visitorType: type } as RestDto;
    return true;
  }
}
